#ifndef otkxstring_h_
#define otkxstring_h_
#include <OTKXMain.h>
#define G_ERROR_SUCCEED 0       //succeed
#define G_ERROR_INVALIDPARAM -1 //invalid param
#define G_ERROR_INTERNAL -2     //internal call error
#define G_ERROR_NOBUF -3        //new buffer failed
namespace gconvert
{
    // ANSI->Unicode
    int ansi2uni(const std::string &ansi, std::wstring &uni);
    // Unicode->ANSI
    int uni2ansi(const std::wstring &uni, std::string &ansi);
    // UTF8->Unicode
    int utf82uni(const std::string &utf8, std::wstring &uni);
    // Unicode->UTF8
    int uni2utf8(const std::wstring &uni, std::string &utf8);
    // ANSI->UTF8
    int ansi2utf8(const std::string &ansi, std::string &utf8);
    // UTF8->ANSI
    int utf82ansi(const std::string &utf8, std::string &ansi);
} // namespace gconvert
enum Encode
{
    ANSI = 1,
    UTF16_LE,
    UTF16_BE,
    UTF8_BOM,
    UTF8
};
__inline static Encode IsUtf8Data(const uint8_t *data, size_t size)
{
    bool bAnsi = true;
    uint8_t ch = 0x00;
    int32_t nBytes = 0;
    for (auto i = 0; i < size; i++)
    {
        ch = *(data + i);
        if ((ch & 0x80) != 0x00)
        {
            bAnsi = false;
        }
        if (nBytes == 0)
        {
            if (ch >= 0x80)
            {
                if (ch >= 0xFC && ch <= 0xFD)
                {
                    nBytes = 6;
                }
                else if (ch >= 0xF8)
                {
                    nBytes = 5;
                }
                else if (ch >= 0xF0)
                {
                    nBytes = 4;
                }
                else if (ch >= 0xE0)
                {
                    nBytes = 3;
                }
                else if (ch >= 0xC0)
                {
                    nBytes = 2;
                }
                else
                {
                    return Encode::ANSI;
                }
                nBytes--;
            }
        }
        else
        {
            if ((ch & 0xC0) != 0x80)
            {
                return Encode::ANSI;
            }
            nBytes--;
        }
    }
    if (nBytes > 0 || bAnsi)
    {
        return Encode::ANSI;
    }
    return Encode::UTF8;
}
__inline static Encode DetectEncode(const uint8_t *data, size_t size)
{
    if (size > 2 && data[0] == 0xFF && data[1] == 0xFE)
    {
        return Encode::UTF16_LE;
    }
    else if (size > 2 && data[0] == 0xFE && data[1] == 0xFF)
    {
        return Encode::UTF16_BE;
    }
    else if (size > 3 && data[0] == 0xEF && data[1] == 0xBB && data[2] == 0xBF)
    {
        return Encode::UTF8_BOM;
    }
    else
    {
        return IsUtf8Data(data, size);
    }
}
#endif
